package mysgoog.bot.algo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;

import mysgoog.board.Board;
import mysgoog.board.DragonBoard;
import mysgoog.board.Worm;
import mysgoog.gtp.Color;
import static mysgoog.bot.algo.Evaluator.*;

/*
 *  @author Wang Xin'An
 */

public class AdvanceSearch {

	private static final int MAX_SIZE = 13 * 13;

	private static Worm[] worms = new Worm[MAX_SIZE];
	// do alphabeta search
	static private int[] buffer = new int[MAX_SIZE];

	static private SearchResult[] result = new SearchResult[MAX_SIZE];
	// avoid duplicate for each worms
	static private boolean[] alreadyHave = new boolean[MAX_SIZE];

	static public LinkedList<SearchResult> Capture(Board board, Color color) {
		Color other = color.complement();
		Evaluator eva = new Evaluator((DragonBoard) board);
		Arrays.fill(result, null);

		int n = 0;
		for (Worm w : board.getWorms(other)) {
			worms[n++] = w;
		}
		for (int w = 0; w < n; ++w) {
			ArrayList<Integer> low = new ArrayList<Integer>();
			ArrayList<Integer> mid = new ArrayList<Integer>();
			ArrayList<Integer> high = new ArrayList<Integer>();
			Arrays.fill(alreadyHave, false);

			for (Integer pos : worms[w]) {
				int search_res = AlphaBetaSearch.Capture(board, pos, buffer); // ab.Defend(board,
				for (int i = 0; i < search_res; ++i) {
					if (board.isLegal(color, buffer[i])) {
						switch (eva.evaluateGrade(buffer[i], color)) {
						case HIGH:
							high.add(buffer[i]);
							break;
						case MID:
							mid.add(buffer[i]);
							break;
						default:
							low.add(buffer[i]);
							break;
						}
					}
				}
				for (Integer go : high) {
					if (!alreadyHave[go]) {
						alreadyHave[go] = true;
						if (result[go] != null) {
							result[go].worms.add(pos);
						} else {
							result[go] = new SearchResult(go, HIGH);
							result[go].worms.add(pos);
						}
					}
				}

				for (Integer go : mid) {
					if (!alreadyHave[go]) {
						alreadyHave[go] = true;
						if (result[go] != null) {
							result[go].worms.add(pos);
						} else {
							result[go] = new SearchResult(go, MID);
							result[go].worms.add(pos);
						}
					}
				}
				for (Integer go : low) {
					if (!alreadyHave[go]) {
						alreadyHave[go] = true;
						if (result[go] != null) {
							result[go].worms.add(pos);
						} else {
							result[go] = new SearchResult(go, LOW);
							result[go].worms.add(pos);
						}
					}
				}
				break;
			}
		}

		LinkedList<SearchResult> finalRes = new LinkedList<SearchResult>();
		for (int i = 0; i < result.length; ++i) {
			if (result[i] != null)
				finalRes.addLast(result[i]);
		}
		return finalRes;
	}

	static public LinkedList<SearchResult> Defend(Board board, Color color,
			int worm) {
		Color other = color.complement();
		Evaluator eva = new Evaluator((DragonBoard) board);
		Arrays.fill(result, null);

		Worm w = board.wormAt(worm);

		ArrayList<Integer> low = new ArrayList<Integer>();
		ArrayList<Integer> mid = new ArrayList<Integer>();
		ArrayList<Integer> high = new ArrayList<Integer>();
		Arrays.fill(alreadyHave, false);

		for (Integer pos : w) {
			int search_res = AlphaBetaSearch.Defend(board, pos, buffer); // ab.Defend(board,
			for (int i = 0; i < search_res; ++i) {
				if (board.isLegal(color, buffer[i])) {
					switch (eva.evaluateGrade(buffer[i], color)) {
					case HIGH:
						high.add(buffer[i]);
						break;
					case MID:
						mid.add(buffer[i]);
						break;
					default:
						low.add(buffer[i]);
						break;
					}
				}
			}
			for (Integer go : high) {
				if (!alreadyHave[go]) {
					alreadyHave[go] = true;
					if (result[go] != null) {
						result[go].worms.add(pos);
					} else {
						result[go] = new SearchResult(go, HIGH);
						result[go].worms.add(pos);
					}
				}
			}

			for (Integer go : mid) {
				if (!alreadyHave[go]) {
					alreadyHave[go] = true;
					if (result[go] != null) {
						result[go].worms.add(pos);
					} else {
						result[go] = new SearchResult(go, MID);
						result[go].worms.add(pos);
					}
				}
			}
			for (Integer go : low) {
				if (!alreadyHave[go]) {
					alreadyHave[go] = true;
					if (result[go] != null) {
						result[go].worms.add(pos);
					} else {
						result[go] = new SearchResult(go, LOW);
						result[go].worms.add(pos);
					}
				}
			}
			break;
		}

		LinkedList<SearchResult> finalRes = new LinkedList<SearchResult>();
		for (int i = 0; i < result.length; ++i) {
			if (result[i] != null)
				finalRes.addLast(result[i]);
		}
		return finalRes;
	}

}
